Scripting | Camera Look At bug

Hi,

I’m building a script and I’ve some trouble with getting the look at point of a camera.
When I use the getCameraLookAt() function, it gives me the pivot point instead of the target point. In my file, both are different.

In my script I have an camera animation, and the script create a new camera, get the target position, camera position and twist then remove the camera and loop until end of animation.

Any other way to get that information ? I’m trying to find a way to get the good target or check the ‘use target as pivot’ before grab camera info, wich should overide pivot data by target data.

Last chance could be to use CameraDirection with CameraDistance, but that include more math operation, what I would like to avoid.

Thanks.

Hey Pierre,

I see the same behavior. For the camera you are running the script on select the check box, “Use Target as Pivot” and when you run the script the Look At will use the target instead of the pivot.

I tested it by entering different values for the camera Target and Pivot and running the following script with “Use Camera Target as Pivot” enabled and disabled. After which I noted the different values between the settings.

import lux

# Get the active camera's look-at point
look_at_point = lux.getCameraLookAt()

# Print the retrieved look-at point (a tuple with x, y, z coordinates)
print("Camera Look-At Point:", look_at_point)

Almost forgot, so you don’t have to do the math.

# AUTHOR LUX DT ChatGPT
# VERSION 1.2.4
# Get Camera settings and display the look-at point.
# Script to view camera details in a window in KeyShot.

import lux  # Import the KeyShot built-in module 'lux'.

def get_camera_info(camera_name):
    """
    Retrieve and format information for a specified camera, including look-at point.

    :param camera_name: Name of the camera to get information about.
    :return: Formatted string containing camera details.
    """
    # Set the selected camera as active.
    lux.setCamera(camera_name)

    # Retrieve various camera details.
    lens_info = lux.getCameraLens()  # Retrieves camera lens information
    fov = round(lux.getCameraFieldOfView(), 2)  # Field of view.
    focal_length = round(lux.getCameraFocalLength(), 2)  # Focal length.

    # Determine the lens type based on camera mode
    lens_type = lens_info.get('lens')
    if lens_type == lux.CAMERA_TYPE_PERSPECTIVE:
        lens_type_str = 'Perspective'
    elif lens_type == lux.CAMERA_TYPE_ORTHOGRAPHIC:
        lens_type_str = 'Orthographic'
    elif lens_type == lux.CAMERA_TYPE_PANORAMA:
        lens_type_str = 'Panoramic'
    else:
        lens_type_str = 'Unknown'

    direction = lux.getCameraDirection()  # Camera direction.
    distance = round(lux.getCameraDistance(), 2)  # Distance from pivot.
    position = lux.getCameraPosition()  # Camera position.
    up_vector = lux.getCameraUp()  # Up vector.
    look_at = lux.getCameraLookAt()  # Get the look-at point.

    # Format the camera information for display.
    camera_info = (
        "Lens Info:\n"
        f"FOV: {fov} degrees\n"
        f"Focal Length: {focal_length} mm\n"
        f"Lens Type: {lens_type_str}\n\n"
        f"Direction: {direction}\n"
        f"Distance: {distance}\n"
        f"Position: {position}\n"
        f"Up Vector: {up_vector}\n"
        f"Look-At Point: {look_at}"
    )
    return camera_info

def display_camera_info(cam):
    """
    Display information of a selected camera.

    :param cam: Name of the camera to display information for.
    :return: Boolean indicating if the user wants to go back to the camera list.
    """
    camera_info = get_camera_info(cam)  # Get camera info.
    info_label = (lux.DIALOG_LABEL, camera_info)  # Format for displaying.
    back_checkbox = ("backToList", lux.DIALOG_CHECK, "Back to Camera List", False)
    
    # Display the camera info in a dialog.
    user_response = lux.getInputDialog(title=f"Camera Info: {cam}", values=[info_label, back_checkbox])

    return user_response and user_response.get("backToList", False)

def display_camera_selection():
    """
    Display a selection dialog for all cameras and show their information.
    """
    cameras = lux.getCameras()  # Get a list of all cameras.
    while True:
        # Create dialog elements for camera selection.
        camera_selection_elements = [(cam, lux.DIALOG_CHECK, cam, False) for cam in cameras]
        user_selection = lux.getInputDialog(title="Select Camera", values=camera_selection_elements)

        if not user_selection:
            break  # Exit if no selection is made.

        # Loop through the selected cameras and display their information.
        for cam, selected in user_selection.items():
            if selected:
                back_to_list = display_camera_info(cam)
                if back_to_list:
                    break  # Return to the camera list if the user chooses.

# Execute the function to start the camera selection process.
display_camera_selection()

Hi Don

Thanks for your answer.
I can’t check the ‘use target as pivot’ on the main camera as my camera animation use a different pivat than target. That’s why I tryed to check that box on my ‘temp’ camera before gathering camera info.
I didn’t find a way to get the target instead of pivot, so I did the math with distance / direction / position. Then it create a liste with all datas and build a csv.

I’ve done that script which works fine for what I need. It could be optimized I guess, I’m not so used to make script and code.
Sorry, I didn’t comment my script too.

# AUTHOR BILL
# VERSION 1.0.0

frames = lux.getAnimationInfo()["frames"]
cameras = lux.getCameras()
data = [
    ['camX','camY','camZ','twist','loatX','loatY','loatZ','frame']
    ]
    
values = [("folder", lux.DIALOG_FOLDER, "Output folder:", None),
          ("filename", lux.DIALOG_TEXT, "Csv filename (no extension)", lux.getCamera()),
          ("camera", lux.DIALOG_ITEM, "Camera to export", lux.getCamera() , cameras),
          ("start", lux.DIALOG_INTEGER, "Start frame:", 1, (1, frames)),
          ("end", lux.DIALOG_INTEGER, "End frame:", frames, (1, frames))]

opts = lux.getInputDialog(title = "Export Camera data",
                              desc = "Build a csv file with camera target, position & twist.",
                              values = values)

if len(opts["folder"]) == 0:
    raise Exception("Folder cannot be empty!") 
if len(opts["filename"]) == 0:
    raise Exception("Filename cannot be empty!")    
if start > end:
    raise Exception("Start frame cannot be larger than end frame!")


fld = opts["folder"]
fname = opts["filename"]
start = opts["start"]-1
end = opts["end"]-1
csvpath = opts['folder'] + "/" + opts['filename'] + '.csv'
cam = opts['camera'][1]

def cameraInfo():
    pos = lux.getCameraPosition()
    twist = (lux.getSphericalCamera()[2],)
    dire = lux.getCameraDirection()
    dist = lux.getCameraDistance()
    vect = luxmath.Vector(dire).mul(dist).val()
    loat = luxmath.Vector(pos).add(vect).val()
    frm = lux.getAnimationFrame()
    return list (pos + twist + loat + (frm,)) 

def cameraBuild():
    global data
    lux.newCamera('temp')
    data = list(data+[cameraInfo()])
    lux.setCamera(cam)
    lux.removeCamera('temp')

def main():
    lux.setCamera(cam)
    lux.setAnimationFrame(start)
    while True : 
        currentframe = lux.getAnimationFrame()
        if currentframe > end:
            break
        cameraBuild()
        lux.setAnimationFrame(currentframe+1)

cameraInfo()
main()

import csv 
with open(csvpath , 'w' , newline='') as csvfile:
    writer = csv.writer(csvfile)
    writer.writerows(data)